package cn.surveyking.server.core.security;

import cn.surveyking.server.domain.dto.ThirdUserView;
import cn.surveyking.server.domain.dto.UserTokenView;
import cn.surveyking.server.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;

import static java.util.Optional.ofNullable;

/**
 * @author huang.cz
 * @since 2023/5/21 22:40
 */
public class TokenAuthenticationProvider implements AuthenticationProvider {
    private final UserService userService;
    private final ThirdJwtTokenUtil thirdJwtTokenUtil;

    public TokenAuthenticationProvider(UserService userService, ThirdJwtTokenUtil thirdJwtTokenUtil) {
        this.userService = userService;
        this.thirdJwtTokenUtil = thirdJwtTokenUtil;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String token = authentication.getName();
        System.out.println();
        // 校验token是否有效
        if (!thirdJwtTokenUtil.validate(token)) {
            throw new BadCredentialsException("token校验失败");
        }
        ThirdUserView userToken = thirdJwtTokenUtil.getUser(token);
        if (!userService.checkUsernameExist(userToken.getLoginName())) {
            throw new BadCredentialsException("token校验失败");
        }
        UserDetails userDetails = userService.loadUserByUsername(userToken.getLoginName());
        return new TokenAuthenticationToken(userDetails, ofNullable(userDetails).map(UserDetails::getAuthorities).orElse(new ArrayList<>()));
    }

    @Override
    public boolean supports(Class<?> authentication) {
        // 被哪种认证方式支持  使用 TokenAuthenticationToken 将会进入进行验证
        return authentication.equals(TokenAuthenticationToken.class);
    }
}